﻿using Microsoft.Phone.Controls;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Geolocation;
using Windows.Foundation;
using XingZhe.Helpers;
using XingZhe.LocationListeners;

namespace XingZhe.Common
{
        public static class GeolocatorManager
        {
                private static List<object> locationListeners = new List<object>();
                private static object lockObject = new object();
                private static Geolocator geolocator = null;
                private static PositionChangedEventArgs lastPositionChangedEventArgs;
                private static bool IsRunning = false;
                static GeolocatorManager()
                {
                        GeolocatorManager.LoadDefaultListeners();
                }
                public static void Start(Action<bool> onComplete)
                {
                        XingZheHelper.LocationConsentMessageBox((b) =>
                        {
                                if (b)
                                {
                                        if (GeolocatorManager.IsRunning == false)
                                        {
                                                lock (GeolocatorManager.lockObject)
                                                {
                                                        if (GeolocatorManager.IsRunning == false)
                                                        {
                                                                GeolocatorManager.IsRunning = true;
                                                                GeolocatorManager.geolocator = new Geolocator()
                                                                {
                                                                        DesiredAccuracy = PositionAccuracy.High,
                                                                        MovementThreshold = 8,
                                                                };

                                                                GeolocatorManager.geolocator.PositionChanged += Geolocator_PositionChanged;
                                                                GeolocatorManager.geolocator.StatusChanged += Geolocator_StatusChanged;
                                                        }
                                                }
                                        }
                                }
                                else
                                {
                                        CustomMessageBox messgeBox = new CustomMessageBox()
                                        {
                                                Caption = "行者",
                                                Message = "因为你不允许访问位置服务，此功能无法启动。",
                                                RightButtonContent = "确定",
                                                IsFullScreen = true
                                        };

                                        messgeBox.Show();
                                }

                                if (onComplete != null)
                                {
                                        onComplete(b);
                                }
                        });
                }

                public static void Stop()
                {
                        if (GeolocatorManager.IsRunning)
                        {
                                lock (GeolocatorManager.lockObject)
                                {
                                        if (GeolocatorManager.IsRunning)
                                        {
                                                GeolocatorManager.IsRunning = false;
                                                GeolocatorManager.geolocator.PositionChanged -= Geolocator_PositionChanged;
                                                GeolocatorManager.geolocator.StatusChanged -= Geolocator_StatusChanged;
                                        }
                                }
                        }
                }
                public static void GetGeopositionAsync(Action<Geoposition> onComplete)
                {
                        GeolocatorManager.Start((b) =>
                        {
                                if (b)
                                {
                                        IAsyncOperation<Geoposition> asyncOperation = GeolocatorManager.geolocator.GetGeopositionAsync();

                                        asyncOperation.Completed = (asyncInfo, asyncStatus) =>
                                        {
                                                if (onComplete != null)
                                                {
                                                        onComplete(asyncInfo.GetResults());
                                                }
                                        };
                                }
                                else
                                {
                                        onComplete(null);
                                }
                        });
                }

                public static void GetGeopositionAsync(TimeSpan maximumAge, TimeSpan timeout, Action<Geoposition> onComplete)
                {
                        GeolocatorManager.Start((b) =>
                        {
                                if (b)
                                {
                                        IAsyncOperation<Geoposition> asyncOperation = GeolocatorManager.geolocator.GetGeopositionAsync(maximumAge, timeout);

                                        asyncOperation.Completed = (asyncInfo, asyncStatus) =>
                                        {
                                                if (onComplete != null)
                                                {
                                                        onComplete(asyncInfo.GetResults());
                                                }
                                        };
                                }
                                else
                                {
                                        onComplete(null);
                                }
                        });
                }
                public static void RequestLocationListener(ILocationListener locationListener)
                {
                        if (locationListener == null)
                        {
                                return;
                        }

                        if (!GeolocatorManager.locationListeners.Contains(locationListener))
                        {
                                GeolocatorManager.locationListeners.Add(locationListener);
                        }

                        if (GeolocatorManager.lastPositionChangedEventArgs != null)
                        {
                                locationListener.PositionChanged(GeolocatorManager.geolocator, GeolocatorManager.lastPositionChangedEventArgs);
                        }
                }
                public static void RequestLocationListener(IPositionChanged locationListener)
                {
                        if (locationListener == null)
                        {
                                return;
                        }

                        if (!GeolocatorManager.locationListeners.Contains(locationListener))
                        {
                                GeolocatorManager.locationListeners.Add(locationListener);
                        }

                        if (GeolocatorManager.lastPositionChangedEventArgs != null)
                        {
                                locationListener.PositionChanged(GeolocatorManager.geolocator, GeolocatorManager.lastPositionChangedEventArgs);
                        }
                }
                public static void RequestLocationListener(IGeoStatusChanged locationListener)
                {
                        if (locationListener == null)
                        {
                                return;
                        }

                        if (!GeolocatorManager.locationListeners.Contains(locationListener))
                        {
                                GeolocatorManager.locationListeners.Add(locationListener);
                        }
                }
                public static void UnrequestLocationListener(object locationListener)
                {
                        if (GeolocatorManager.locationListeners.Contains(locationListener))
                        {
                                GeolocatorManager.locationListeners.Remove(locationListener);
                        }
                }

                private static void Geolocator_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
                {
                        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                             {
                                     GeolocatorManager.lastPositionChangedEventArgs = args;

                                     foreach (object listener in GeolocatorManager.locationListeners)
                                     {
                                             if (listener is IPositionChanged)
                                             {
                                                     ((IPositionChanged)listener).PositionChanged(sender, args);
                                             }
                                     }
                             });
                }
                private static void Geolocator_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
                {
                        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
                             {
                                     foreach (object listener in GeolocatorManager.locationListeners)
                                     {
                                             if (listener is IGeoStatusChanged)
                                             {
                                                     ((IGeoStatusChanged)listener).StatusChanged(sender, args);
                                             }
                                     }
                             });
                }
                private static void LoadDefaultListeners()
                {
                        GeolocatorManager.RequestLocationListener(new StatusChangeListener());
                }
        }
}
